1 module hip.component.base;
2 
3 interface IComponent
4 {
5     int getID();
6     string getName();
7 }
8 
9 /**
10  * Adds each of the components to the class. If they contain a mixin template called `ExpandFields`, it will
11  be automatically mixed in.
12  * Params - Components - A list of IBaseComponent implementations
13  * Best Practice: Use `pragma(inline, true)` and `final` if they are a function, as could be a significant difference in the binary
14  * ExpandFields Example :
15  ```d
16  mixin template ExpandFields() ///Expand fields from BodyRectComponent
17 { //Used for convenient access without needing to use _BodyRectComponent.position.x
18     pragma(inline, true)
19     {
20         final ref float x(){ return _BodyRectComponent.position.x; }
21         final ref float y(){ return _BodyRectComponent.position.y; }
22         final ref Vector2 velocity(){ return _BodyRectComponent.velocity; }
23         final ref Vector2 position(){ return _BodyRectComponent.position; }
24         final ref Size size(){ return _BodyRectComponent.size; }
25     }
26 }
27  ```
28  */
29 mixin template IncludeComponents(Components...)
30 {
31     static assert(is(typeof(this) : IComponentizable));
32     private IComponent[] components;
33     static foreach(C; Components)
34     {
35         static assert(is(C : IComponent), C.stringof ~ " is not a component!");
36         mixin("private C _"~__traits(identifier, C)~";");
37 
38         static if(__traits(compiles, __traits(getMember, C, "ExpandFields")))
39             mixin C.ExpandFields;
40     }
41 
42     void initializeComponents()
43     {
44         static if(is(typeof(super) : IComponentizable))
45             super.initializeComponents();
46         static foreach(C; Components)
47         {
48             components~= __traits(getMember, typeof(this), "_"~__traits(identifier, C)) = new C();
49         }
50     }
51 
52     /**
53      * Used more internally in the class. It returns the component in compilation time and gives
54      * a compilation failure if it doesn't exists
55      * Returns: The Component evaluated in compilation time
56      */
57     T Get(T)()
58     {
59         return mixin("_",__traits(identifier, T));
60     }
61     IComponent getComponentBase(int id)
62     {
63         foreach(c; components)
64             if(c.getID() == id)
65                 return c;
66         return null;
67     }
68 }
69 
70 class IBaseComponent(T) : IComponent
71 {
72     final int getID(){return getComponentID!T;}
73     final string getName(){return __traits(identifier, T);}
74 }
75 
76 interface IComponentizable
77 {
78     IComponent getComponentBase(int id);
79     T getComponent(T)() if(is(T : IComponent)) {return cast(T)getComponentBase(getComponentID!T);}
80 
81 }
82 
83 private __gshared int compID = 0;
84 private int getComponentID(T)()
85 {
86     __gshared int _compId = 0;
87     if(_compId == 0)
88         _compId = ++compID;
89     return _compId;
90 }